import ui

class Memory(object):
    """
    implementation of an arbitrary amount of memory as a flat byte-array.

    >>> memory = Memory(0x10000) # 64k
    >>> memory.load(0xFFFE, [0x00, 0x10])
    >>> memory[0xFFFE]
    0
    >>> memory[0xFFFF]
    16
    """

    def __init__(self, size):
        """
        initialize memory of the given size.
        """
        self._mem = [0x00] * size

    def __getitem__(self, address):
        """
        get the byte at the given address.
        """
        if 0xC000 <= address <= 0xCFFF:
            print "tried to read", hex(address)
            if address == 0xC000:
                return self._mem[address] # @@@ could just poll keyboard here?
            elif address == 0xC010:
                self._mem[0xC000] &= 0x7F
                return 0x00
            elif address in [0xC030, 0xC051, 0xC054, 0xC056, 0xC058, 0xC05A, 0xC05D, 0xC05F, 0xCFFF, 0xC010, 0xC707, 0xC607, 0xC507, 0xC407, 0xC307, 0xC207, 0xC107, 0xC100, 0xC200, 0xC300, 0xC400, 0xC500, 0xC600, 0xC700, 0xC800, 0xC900, 0xCA00, 0xCB00, 0xCC00, 0xCD00, 0xCE00, 0xCF00]:
                return self._mem[address]
            else:
                import sys; sys.exit(1)
        else:
            return self._mem[address]

    def __setitem__(self, address, value):
        """
        set the value of the given address to the give byte value.
        """
        if 0xC000 <= address <= 0xCFFF:
            if address == 0xC000:
                self._mem[address] = value
            elif address == 0xC010:
                self._mem[0xC000] &= 0x7F
            else:
                print "tried to write", hex(address), hex(value)
                import sys; sys.exit(1)
        elif 0x0400 <= address <= 0x7FF:
            self._mem[address] = value
            ui.text(address, value)
        else:
            self._mem[address] = value
    
    def load(self, address, data):
        """
        loads the list of bytes in data into memory starting at the given address.
        """
        for i, datum in enumerate(data):
            self._mem[address + i] = datum

    def load_file(self, address, filename):
        """
        loads the given file into memory at the given address.
        """
        for i, datum in enumerate(open(filename, "rb").read()):
            self._mem[address + i] = ord(datum)

    def callback(self):
        ui.check_keyboard(self)
